﻿//TODO: Maybe eliminate?, MyOwnMeanShift

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// Meanshift function
    /// </summary>
    public class MyOwnMeanShift : BaseImageFilter
    {
        /// <summary>
        /// default constructor
        /// </summary>
        public MyOwnMeanShift()
        {
        }

        /// <summary>
        /// used by clone to create a deep copy
        /// </summary>
        /// <param name="_myOwnMeanShift"></param>
        internal MyOwnMeanShift(MyOwnMeanShift _myOwnMeanShift)
        {
        }

        /// <summary>
        /// Executes this filter.
        /// </summary>
        /// <param name="bitmap">The bitmap.</param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap bitmap)
        {
            List<ColorRect> m_aRect = new List<ColorRect>();
            List<ColorRect> m_aRect2 = new List<ColorRect>();
            Hashtable m_aHashrect = new Hashtable();

            List<Color> aColor = new List<Color>() { bitmap.GetPixel(0, 0) };
            List<Rectangle> aRect = new List<Rectangle>();

            int nCount = 1;
            Rectangle rectTemp = Rectangle.Empty;

            int nColorCount = 0;

            int nHeight = bitmap.Height;
            int nWidth = bitmap.Width;

            //1. Durchgang
            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 1; x < nWidth; x++)
                {
                    Color color = bitmap.GetPixel(x, y);
                    aColor.Add(color);
                    if (
                        Math.Abs(aColor[nCount - 1].R - aColor[nCount].R) < 6
                     && Math.Abs(aColor[nCount - 1].G - aColor[nCount].G) < 6
                     && Math.Abs(aColor[nCount - 1].B - aColor[nCount].B) < 6
                    )
                    {
                        if (rectTemp == Rectangle.Empty)
                        {
                            rectTemp = new Rectangle(x, y, 1, 1);
                        }
                        rectTemp = Rectangle.Union(rectTemp, new Rectangle(x - 1, y, 1, 1));
                    }
                    else
                    {
                        if ((rectTemp != Rectangle.Empty))
                        {
                            //ColorRect rect = new ColorRect(bitmap.GetPixel(rectTemp.X, rectTemp.Y), rectTemp);
                            ColorRect colorRect = new ColorRect(Color.Gray, rectTemp);
                            m_aRect.Add(colorRect);

                            if (!m_aHashrect.ContainsKey(colorRect.Rectangle.Y))
                            {
                                m_aHashrect.Add(colorRect.Rectangle.Y, new List<ColorRect>() { colorRect });
                            }
                            else
                            {
                                List<ColorRect> aRectangle = (List<ColorRect>)m_aHashrect[colorRect.Rectangle.Y];
                                aRectangle.Add(colorRect);
                            }

                            aRect.Add(rectTemp);
                        }
                        rectTemp = Rectangle.Empty;
                        nColorCount++;
                        //break;
                    }
                    nCount++;
                }
            }

            //2. Durchgang (Join Rectangles)
            Rectangle lastRectangle = m_aRect[0].Rectangle;
            Rectangle currentRectangle = Rectangle.Empty;
            Rectangle newRectangle = Rectangle.Empty;
            Color currentColor = Color.Transparent;
            Color lastColor = Color.Transparent;

            List<Rectangle> aRectJoinTemp = new List<Rectangle>();
            for (int z = 0; z < 5; z++)
            {
                for (int i = 1; i < m_aHashrect.Count; i++)
                {
                    List<ColorRect> aRectHashLast = (List<ColorRect>)m_aHashrect[i - 1];
                    List<ColorRect> aRectHashCurrent = (List<ColorRect>)m_aHashrect[i];
                    for (int j = 0; j < aRectHashLast.Count; j++)
                    {
                        for (int k = 0; k < aRectHashCurrent.Count; k++)
                        {
                            currentRectangle = aRectHashCurrent[k].Rectangle;
                            currentColor = aRectHashCurrent[k].Color;

                            lastColor = aRectHashLast[j].Color;
                            lastRectangle = aRectHashLast[j].Rectangle;

                            if (lastRectangle.IntersectsWithInclusive(currentRectangle)
                                &&
                                (Math.Abs(currentColor.R - lastColor.R) < 6
                                    && Math.Abs(currentColor.G - lastColor.G) < 6
                                    && Math.Abs(currentColor.B - lastColor.B) < 6
                                )
                                )
                            {
                                newRectangle = Rectangle.Union(lastRectangle, currentRectangle);
                            }
                        }
                    }
                }
            }
            return bitmap;
        }

        /// <summary>
        /// This is used to clone a filter, each filter must implement it's own clone functionality
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new MyOwnMeanShift(this);
        }
    }
}
